/**
 * 
 */
package cn.biplam.back.bean.tree;

import java.util.ArrayList;
import java.util.Map;

import cn.biplam.back.jda.Jda;
import cn.biplam.back.sql.select.BaseSelect;
import cn.biplam.common.bean.sqlengine.Sql;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.sqlresult.SqlResult;

/**
 * 查找指定树形表某节点的所有下级节点ID
 * @author 	WangSong 2009-10-23 上午09:13:49
 * @version 1.0
 */
public class FindChildren {

	private DbResource dbResource;
	private ArrayList<String> arNodeList;
	private BaseSql baseSql;
	private String findField;

	/**
	 * 构造方法
	 * @param dbResource	数据源(指定查询请求的数据源)
	 * @param tableName		树形表名称
	 * @param keyField		主键字段名称
	 * @param parentField	上级字段名称
	 * @param keyID			开始节点的主键ID
	 * @throws ErrorMessage 
	 */
	public FindChildren(DbResource dbResource,String tableName,String keyField,String parentField,String keyID) throws ErrorMessage{
		this(dbResource, tableName, keyField, parentField, keyID, keyField);
	}

	/**
	 * 构造方法
	 * @param dbResource	数据源(指定查询请求的数据源)
	 * @param tableName		树形表名称
	 * @param keyField		主键字段名称
	 * @param parentField	上级字段名称
	 * @param keyID			开始节点的主键ID
	 * @param findField		查找的字段名称
	 * @throws ErrorMessage
	 */
	public FindChildren(DbResource dbResource,String tableName,String keyField,
			String parentField,String keyID,String findField) throws ErrorMessage{
		this.dbResource=dbResource;
		this.baseSql=new BaseSql(tableName,keyField,parentField,findField);
		this.baseSql.setKeyID(keyID);
		this.findField=findField;
		this.arNodeList=new ArrayList<String>();
	}

	/**
	 * 放入一个字符类型过滤条件
	 * @param filterFieldName	过滤字段名
	 * @param filterValue		过滤值
	 * @throws ErrorMessage
	 */
	public void putFilter(String filterFieldName,String filterValue) throws ErrorMessage{
		this.baseSql.putFilter(filterFieldName, filterValue);
	}
	
	/**
	 * 返回下级节点的ArrayList
	 * @return	ArrayList<String>
	 */
	public ArrayList<String> getNodeList(){
		return this.arNodeList;
	}

	/**
	 * 返回下级节点的可用于sql in子句的列表('a','b')
	 * @return	String
	 */
	public String getSqlList(){
		if(this.arNodeList.size()<1){
			return null;
		}
		StringBuilder sb = new StringBuilder();
		for(String ite:this.arNodeList){
			sb.append('\'');
			sb.append(ite);
			sb.append("',");
		}
		sb.delete(sb.length()-1, sb.length());
		return sb.toString();
	}


	
	/**
	 * 开始查找下级节点
	 * @throws ErrorMessage 
	 */
	public void start() throws ErrorMessage{
		/**查找直接下级*/
		Jda jda = new Jda(this.dbResource,false);
		try{
			this.find(jda, this.baseSql,this.arNodeList);
		}finally{
			jda.connClose();
		}
	}

	/**
	 * 递归查找
	 * @param db		创建好的数据源
	 * @param baseSql	查询下级节点的基础SQL(使用时附加上keyID)
	 * @param keyId		主键字段ID值
	 * @throws ErrorMessage 
	 */
	protected void find(Jda jda,BaseSql baseSql,ArrayList<String> arNodeList) throws ErrorMessage{
		SqlResult rs = jda.executeSelect(new Sql(baseSql.toString()));
		while(rs.next()){
			String curKeyID=rs.get(rs.getCurrentRow(), this.findField);
			if(baseSql.haveFilter()){//如果设置了过滤条件,检查条件是否满足
				if(baseSql.checkValue(rs)){
					arNodeList.add(curKeyID);
				}
			}else{//没有设置过滤条件,直接添加
				arNodeList.add(curKeyID);
			}
			//设置下次过滤的主键
			baseSql.setKeyID(rs.getString(0));
			this.find(jda, baseSql,arNodeList);
		}
	}
	
	/**
	 * 递归时使用的基础Sql参数<BR>
	 * 为支持用多个过滤参数生成每次递归查询所需Sql而创建<BR>
	 * 为对查询结果的过滤提供处理方法,因为过滤字段存在本类中
	 */
	public class BaseSql{
		
		
		BaseSelect select;
		KvMap<String, String> filters=new KvMap<String, String>();
		private String parentField;
		private boolean haveFilter=false;

		public BaseSql(String tableName,String keyField,String parentField) throws ErrorMessage{
			this.select=new BaseSelect(tableName);
			this.select.putField(keyField);
			this.parentField=parentField;
		}
		public BaseSql(String tableName,String keyField,String parentField,String findField) throws ErrorMessage{
			this.select=new BaseSelect(tableName);
			this.select.putField(keyField);
			this.parentField=parentField;
			this.select.putField(findField);
		}
		
		/**
		 * 放入一个过滤条件
		 */
		public void putFilter(String filterFieldName,String filterValue) throws ErrorMessage{
			this.haveFilter=true;
			this.filters.put(filterFieldName, filterValue);
			this.select.putField(filterFieldName);
		}
		
		public boolean haveFilter(){
			return this.haveFilter;
		}
		
		/**
		 * 设置主键过滤条件
		 * @param keyID
		 * @throws ErrorMessage
		 */
		public void setKeyID(String keyID) throws ErrorMessage{
			this.select.putStringFilter(this.parentField, keyID);
		}

		
		/**
		 * 传入SqlResult,按过滤条件比较该记录是否符合过滤
		 */
		public boolean checkValue(SqlResult rs) throws ErrorMessage{
			String value;
			for(Map.Entry<String, String>ite:this.filters){
				value=rs.getString(ite.getKey());
				if(!ite.getValue().equals(value)){
					return false;
				}
			}
			return true;
		}

		
		/**
		 * 返回标准sql表达式
		 * @return	String
		 */
		@Override	
		public String toString(){
			return this.select.toString();
		}
	}
	
}
